feat!: extract ScriptGoogleMapsStaticMap as standalone component#673
feat!: extract ScriptGoogleMapsStaticMap as standalone component#673
ScriptGoogleMapsStaticMap as standalone component#673Conversation
…omponent
BREAKING CHANGE: Remove `placeholderOptions`, `placeholderAttrs`, and `aboveTheFold` props from ScriptGoogleMaps. The built-in static map placeholder image is no longer rendered by default.
Use the new `ScriptGoogleMapsStaticMap` component in the `#placeholder` slot instead:
```vue
<ScriptGoogleMaps :center="center" :zoom="7">
<template #placeholder>
<ScriptGoogleMapsStaticMap :center="center" :zoom="7" loading="eager" />
</template>
</ScriptGoogleMaps>
```
The new component can also be used standalone (store locators, contact pages, etc.) and fixes the percentage width/height bug that produced invalid Static Maps API `size` parameters by auto-measuring rendered dimensions on mount.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughRemoved placeholder-related props and logic from packages/script/src/runtime/components/GoogleMaps/ScriptGoogleMaps.vue (deleted props: aboveTheFold, placeholderOptions, placeholderAttrs; removed Static Maps placeholder generation and fallback Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@packages/script/src/runtime/components/GoogleMaps/ScriptGoogleMapsStaticMap.vue`:
- Around line 110-112: The component currently prefers the runtime proxy
unconditionally and strips a component-level key; change the logic so an
explicit props.apiKey always wins: compute apiKey = props.apiKey ??
scriptRuntimeConfig('googleMaps')?.apiKey and only choose the proxy (proxyConfig
/ googleStaticMapsProxy) when props.apiKey is not provided and the proxy is
actually enabled/usable; update the proxy selection/use sites (references:
apiKey, props.apiKey, proxyConfig, scriptRuntimeConfig, googleStaticMapsProxy)
and apply the same guard in the other similar branch mentioned.
- Around line 32-34: The TypeScript type for the static map "scale" prop
currently allows 1 | 2 | 4 which is invalid for Google Static Maps; update the
prop/type definition for "scale" (in ScriptGoogleMapsStaticMap.vue) to only
allow 1 | 2, and update any related validation/usage sites (prop default, prop
validator, or URL-building code that reads "scale") to reflect the two allowed
values so callers cannot generate scale=4 URLs.
- Around line 122-129: Auto-measured and derived sizes are being assigned
directly to measuredSize (in the onMounted block and the derived-size branch
around lines 176–184), which can produce dimensions exceeding Google Static Maps
limits; update the logic in onMounted and the derived-size computation to
clamp/scale down the measured width/height proportionally to fit within the
allowed max (use 640x640 as the base max or 1280x1280 when props.scale === 2)
while preserving aspect ratio, and only set measuredSize when the clamped
dimensions are used; keep props.size as the override/escape hatch and reference
measuredSize, rootEl, props.size and props.scale when implementing the clamp.
In `@playground/pages/third-parties/google-maps/nuxt-scripts.vue`:
- Around line 27-33: The checked-in literal Google Maps API key should be
removed and replaced with a runtime-config/env binding: add a shared key
variable (e.g., googleMapsApiKey) sourced from runtime config or an env var
(useRuntimeConfig()/process.env.NUXT_PUBLIC_GOOGLE_MAPS_API_KEY) and bind it to
the components instead of the hard-coded string; update the
ScriptGoogleMapsStaticMap component's api-key prop to use
:api-key="googleMapsApiKey" and do the same for the other map component(s) on
the page so both reuse the single runtime-config-sourced value.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 4e9f14cb-119c-4bdf-9234-530e5894d314
📒 Files selected for processing (13)
packages/script/src/runtime/components/GoogleMaps/ScriptGoogleMaps.vuepackages/script/src/runtime/components/GoogleMaps/ScriptGoogleMapsStaticMap.vueplayground/pages/third-parties/google-maps/center.vueplayground/pages/third-parties/google-maps/emit-test.vueplayground/pages/third-parties/google-maps/geojson-test.vueplayground/pages/third-parties/google-maps/markers.vueplayground/pages/third-parties/google-maps/null.vueplayground/pages/third-parties/google-maps/nuxt-scripts.vueplayground/pages/third-parties/google-maps/overlay-animated.vueplayground/pages/third-parties/google-maps/overlay-popup.vueplayground/pages/third-parties/google-maps/query.vueplayground/pages/third-parties/google-maps/sfcs.vueplayground/pages/third-parties/google-maps/styled.vue
💤 Files with no reviewable changes (10)
- playground/pages/third-parties/google-maps/geojson-test.vue
- playground/pages/third-parties/google-maps/styled.vue
- playground/pages/third-parties/google-maps/query.vue
- playground/pages/third-parties/google-maps/markers.vue
- playground/pages/third-parties/google-maps/center.vue
- playground/pages/third-parties/google-maps/overlay-animated.vue
- playground/pages/third-parties/google-maps/overlay-popup.vue
- playground/pages/third-parties/google-maps/sfcs.vue
- playground/pages/third-parties/google-maps/emit-test.vue
- playground/pages/third-parties/google-maps/null.vue
| * Device pixel ratio for the static map image (1, 2, or 4). | ||
| */ | ||
| scale?: 1 | 2 | 4 |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Google Maps Static API scale parameter documentation
💡 Result:
The scale parameter in the Google Maps Static API is an optional URL parameter that controls the pixel density of the returned map image. It is particularly useful for high-resolution displays like Retina screens. Key details: - Default value: 1 - Accepted values: 1 or 2 (doubles the pixels while keeping the same map coverage area and detail level) - Interaction with size: The final image dimensions are size width/height multiplied by scale (e.g., size=400x300&scale=2 produces an 800x600 pixel image). - Purpose: Provides sharper images on high-DPI screens without changing the zoom or visible area; roads and labels remain legible. - Limits: Standard max size 640x640 pixels (or 1280x1280 with scale=2); larger sizes may require support contact. - Note on markers: There is a separate scale descriptor for markers (1,2,4) prefixed as 'scale:N' in the markers parameter. Example URL: https://maps.googleapis.com/maps/api/staticmap?center=Brooklyn+Bridge,New+York,NY&zoom=13&size=600x300&scale=2&key=YOUR_API_KEY Official documentation is in the "Get Started" guide at developers.google.com/maps/documentation/maps-static/start, under URL Parameters and Scale Values section.
Citations:
- 1: https://developers.google.com/maps/documentation/maps-static/overview
- 2: https://developers.google.com/maps/documentation/maps-static/start
- 3: https://developers.google.com/maps/documentation/maps-static/usage-and-billing
- 4: https://developers.google.com/maps/documentation/maps-static/start?hl=es-419
- 5: https://via.30lines.com/I5AzWpYp
Restrict scale to values the Static Maps API actually accepts.
The Google Maps Static API only accepts scale=1 or scale=2. Allowing scale=4 in the type definition enables type-safe code to generate rejected image URLs.
Suggested fix
- /**
- * Device pixel ratio for the static map image (1, 2, or 4).
- */
- scale?: 1 | 2 | 4
+ /**
+ * Device pixel ratio for the static map image (1 or 2).
+ */
+ scale?: 1 | 2🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@packages/script/src/runtime/components/GoogleMaps/ScriptGoogleMapsStaticMap.vue`
around lines 32 - 34, The TypeScript type for the static map "scale" prop
currently allows 1 | 2 | 4 which is invalid for Google Static Maps; update the
prop/type definition for "scale" (in ScriptGoogleMapsStaticMap.vue) to only
allow 1 | 2, and update any related validation/usage sites (prop default, prop
validator, or URL-building code that reads "scale") to reflect the two allowed
values so callers cannot generate scale=4 URLs.
packages/script/src/runtime/components/GoogleMaps/ScriptGoogleMapsStaticMap.vue
Outdated
Show resolved
Hide resolved
| onMounted(() => { | ||
| if (props.size || !rootEl.value) | ||
| return | ||
| const { offsetWidth, offsetHeight } = rootEl.value | ||
| if (offsetWidth > 0 && offsetHeight > 0) { | ||
| measuredSize.value = `${offsetWidth}x${offsetHeight}` | ||
| } | ||
| }) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find . -name "ScriptGoogleMapsStaticMap.vue" -type fRepository: nuxt/scripts
Length of output: 137
🏁 Script executed:
cat -n ./packages/script/src/runtime/components/GoogleMaps/ScriptGoogleMapsStaticMap.vue | sed -n '110,190p'Repository: nuxt/scripts
Length of output: 3483
🌐 Web query:
Google Maps Static API size limits 640x640
💡 Result:
The Google Maps Static API has a standard maximum image size of 640x640 pixels. With scale=2, this effectively allows up to 1280x1280 pixels (twice the pixels while retaining the same coverage area). Sizes larger than 640x640 (or 1280x1280 with scale=2) require contacting Google support for approval on a case-by-case basis, with a maximum possible size of 2048x2048 pixels if approved. Maps smaller than 180 pixels wide show a reduced Google logo. The size parameter is specified as widthxheight (e.g., size=640x640). URL length is limited to 16384 characters.
Citations:
- 1: https://developers.google.com/maps/documentation/maps-static/start
- 2: https://developers.google.com/maps/documentation/maps-static/usage-and-billing
- 3: https://developers.google.com/maps/documentation/maps-static/start?hl=es-419
- 4: https://developers.google.com/maps/documentation/maps-static/start?hl=fr
Clamp auto-measured sizes before assigning to size.
The measured/derived branches pass raw CSS pixels directly to the Google Maps Static API, which has a standard limit of 640×640 pixels (or 1280×1280 with scale=2). Larger dimensions require explicit approval. A standalone width: 100% map can easily exceed this limit on desktop and generate a broken URL. Keep explicit props.size as the escape hatch, but scale down auto-measured and derived values proportionally to fit within the standard constraints.
Clamping function to enforce size limits
+function clampAutoSize(width: number, height: number, max = 640): string {
+ const ratio = Math.min(1, max / Math.max(width, height))
+ return `${Math.max(1, Math.floor(width * ratio))}x${Math.max(1, Math.floor(height * ratio))}`
+}
+
onMounted(() => {
if (props.size || !rootEl.value)
return
const { offsetWidth, offsetHeight } = rootEl.value
if (offsetWidth > 0 && offsetHeight > 0) {
- measuredSize.value = `${offsetWidth}x${offsetHeight}`
+ measuredSize.value = clampAutoSize(offsetWidth, offsetHeight)
}
})
@@
// SSR fallback: derive from width/height if both are pixel values
if (isPixelValue(props.width) && isPixelValue(props.height))
- return `${Number.parseInt(String(props.width))}x${Number.parseInt(String(props.height))}`
+ return clampAutoSize(Number.parseInt(String(props.width)), Number.parseInt(String(props.height)))
return '640x400'
})Also applies to: lines 176-184
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@packages/script/src/runtime/components/GoogleMaps/ScriptGoogleMapsStaticMap.vue`
around lines 122 - 129, Auto-measured and derived sizes are being assigned
directly to measuredSize (in the onMounted block and the derived-size branch
around lines 176–184), which can produce dimensions exceeding Google Static Maps
limits; update the logic in onMounted and the derived-size computation to
clamp/scale down the measured width/height proportionally to fit within the
allowed max (use 640x640 as the base max or 1280x1280 when props.scale === 2)
while preserving aspect ratio, and only set measuredSize when the clamped
dimensions are used; keep props.size as the override/escape hatch and reference
measuredSize, rootEl, props.size and props.scale when implementing the clamp.
| <ScriptGoogleMapsStaticMap | ||
| :center="mapOptions.center" | ||
| :width="640" | ||
| :height="500" | ||
| loading="eager" | ||
| api-key="AIzaSyAOEIQ_xOdLx2dNwnFMzyJoswwvPCTcGzU" | ||
| /> |
There was a problem hiding this comment.
Remove the checked-in Google Maps key from the playground.
Line 32 adds another hard-coded Maps credential to the repository. Even if it's restricted, committed cloud keys leak into forks, preview deployments, and published artifacts. Please switch this page to a runtime-config/env binding and reuse that value for both map components instead of duplicating the literal inline.
🧰 Tools
🪛 Betterleaks (1.1.1)
[high] 32-32: Uncovered a GCP API key, which could lead to unauthorized access to Google Cloud services and data breaches.
(gcp-api-key)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@playground/pages/third-parties/google-maps/nuxt-scripts.vue` around lines 27
- 33, The checked-in literal Google Maps API key should be removed and replaced
with a runtime-config/env binding: add a shared key variable (e.g.,
googleMapsApiKey) sourced from runtime config or an env var
(useRuntimeConfig()/process.env.NUXT_PUBLIC_GOOGLE_MAPS_API_KEY) and bind it to
the components instead of the hard-coded string; update the
ScriptGoogleMapsStaticMap component's api-key prop to use
:api-key="googleMapsApiKey" and do the same for the other map component(s) on
the page so both reuse the single runtime-config-sourced value.
ScriptGoogleMapsStaticMap as standalone component
- Restrict scale prop to 1 | 2 (matches Static Maps API) - Explicit apiKey prop now takes priority over proxy - Clamp auto-measured sizes to 640x640 API limit - Remove hardcoded API key from playground - Add ScriptGoogleMapsStaticMap API doc page - Update ScriptGoogleMaps docs for new placeholder pattern - Add Google Maps breaking changes to v0-to-v1 migration guide
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
docs/content/scripts/google-maps/2.api/1b.static-map.md (1)
81-84: Address passive voice to fix pipeline warnings.Consider rewriting to use active voice:
📝 Suggested rewrite
-When `googleMaps` is configured in `scripts.registry`, a server-side proxy is automatically enabled. The component routes requests through the proxy unless an explicit `apiKey` prop is provided. +Configuring `googleMaps` in `scripts.registry` automatically enables a server-side proxy. The component routes requests through the proxy unless you provide an explicit `apiKey` prop.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/content/scripts/google-maps/2.api/1b.static-map.md` around lines 81 - 84, The "Proxy Support" paragraph uses passive voice; rewrite it in active voice and keep the same meaning: state that when you configure googleMaps in scripts.registry the system enables a server-side proxy, and clarify that the component routes requests through that proxy unless the consumer provides an explicit apiKey prop (reference: "googleMaps", "scripts.registry", "apiKey" prop, "Proxy Support" heading).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/content/docs/4.migration-guide/1.v0-to-v1.md`:
- Line 338: Rewrite the passive sentence on line 338 to active voice; replace
"The new component can also be used standalone for store locators, contact
pages, and directions previews without loading the interactive Maps API." with
an active construction that names the actor (e.g., "You can use the new
component standalone for store locators, contact pages, and directions previews
without loading the interactive Maps API." or "Developers can use the new
component standalone for...") so the sentence is direct and in active voice.
- Around line 304-312: The documentation uses passive voice and the pipeline
flags it; update the section describing the Google Maps Static Placeholder to
active voice by rewriting sentences that currently use passive
construction—refer to the component and props by name
(ScriptGoogleMapsStaticMap, <ScriptGoogleMaps>, and the removed props
placeholderOptions, placeholderAttrs, aboveTheFold, plus the `#placeholder` slot)
and change wording to active phrasing (e.g., "We extracted the built-in static
map placeholder into the standalone ScriptGoogleMapsStaticMap component" and
"The following props were removed from <ScriptGoogleMaps>: ..."; ensure the
`#placeholder` slot description states explicitly that it no longer passes a
placeholder URL and is empty by default).
In `@docs/content/scripts/google-maps/2.api/1b.static-map.md`:
- Around line 48-69: The props table uses em-dashes (—) in the Default column
causing pipeline failures; edit the table rows for props like `center`,
`format`, `maptype`, `mapId`, `markers`, `path`, `visible`, `style`, `language`,
`region`, `signature`, `apiKey`, and `imgAttrs` and replace each em-dash with
either an explicit value like "none" or an empty cell (i.e., remove the em-dash)
so the Default column contains plain ASCII text; ensure all occurrences are
updated consistently across the table so the markdown renderer and pipeline no
longer error.
---
Nitpick comments:
In `@docs/content/scripts/google-maps/2.api/1b.static-map.md`:
- Around line 81-84: The "Proxy Support" paragraph uses passive voice; rewrite
it in active voice and keep the same meaning: state that when you configure
googleMaps in scripts.registry the system enables a server-side proxy, and
clarify that the component routes requests through that proxy unless the
consumer provides an explicit apiKey prop (reference: "googleMaps",
"scripts.registry", "apiKey" prop, "Proxy Support" heading).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 6244561d-0002-4788-9647-df8f5848ba9b
📒 Files selected for processing (5)
docs/content/docs/4.migration-guide/1.v0-to-v1.mddocs/content/scripts/google-maps/2.api/1.script-google-maps.mddocs/content/scripts/google-maps/2.api/1b.static-map.mdpackages/script/src/runtime/components/GoogleMaps/ScriptGoogleMapsStaticMap.vueplayground/pages/third-parties/google-maps/nuxt-scripts.vue
✅ Files skipped from review due to trivial changes (1)
- playground/pages/third-parties/google-maps/nuxt-scripts.vue
🔗 Linked issue
Related to #594
❓ Type of change
📚 Description
The static map placeholder was tightly coupled inside
ScriptGoogleMaps, creating several issues: percentage width/height produced invalidsizeparameters for the Static Maps API, there was no way to disable the placeholder, andplaceholderOptions/placeholderAttrs/aboveTheFoldwere a confusing three-prop surface for one concept.This extracts the static map into a standalone
<ScriptGoogleMapsStaticMap>component that can be used independently (store locators, contact pages, directions previews) or dropped into the#placeholderslot ofScriptGoogleMaps.The new component auto-measures its rendered pixel dimensions on mount, so percentage-based CSS sizing works correctly. It also supports multiple markers/paths via string arrays, accepts both raw Static Maps API style strings and JS API
MapTypeStyle[]objects, and handles the proxy/direct API key logic.Removed from
ScriptGoogleMaps:placeholderOptionspropplaceholderAttrspropaboveTheFoldpropPlaceholderOptionsexported type<img>in the default#placeholderslotThe
#placeholderslot is now empty by default. The slot propplaceholder(URL string) is no longer passed.📝 Migration